﻿using QS.Tool.Common.EncryptDecrypt;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;


namespace QS.Tool.Common.WaterMark
{
    public class WaterMarkHelper
    {
        private static Dictionary<string, Dictionary<float, float>> dic = new Dictionary<string, Dictionary<float, float>>();
        private static Dictionary<float, float> dicXY = new Dictionary<float, float>();
        /// <summary>
        /// 图片水印
        /// </summary>
        /// <param name="imgPath">图片路径</param>
        /// <param name="filename">保存文件名及路径</param>
        /// <param name="watermarkFilename">水印文件路径</param>
        /// <param name="watermarkStatus">图片水印位置 </param>
        /// <param name="quality">附加水印图片质量,0-100</param>
        /// <param name="watermarkTransparency">水印的透明度 1--10 10为不透明</param>
        public static void AddImageSignPic(string imgPath, string filename, string watermarkFilename, int watermarkStatus, int quality, int watermarkTransparency)
        {
            if (!File.Exists(imgPath))
            {
                return;
            }
            byte[] _ImageBytes = File.ReadAllBytes(imgPath);
            Image img = Image.FromStream(new MemoryStream(_ImageBytes));

            if (watermarkFilename.StartsWith("/") == false)
                watermarkFilename = "/" + watermarkFilename;
            if (!File.Exists(watermarkFilename))
            {
                return;
            }
            Graphics g = Graphics.FromImage(img);
            //设置高质量插值法
            //g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
            //设置高质量,低速度呈现平滑程度
            //g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            Image watermark = new Bitmap(watermarkFilename);

            if (watermark.Height >= img.Height || watermark.Width >= img.Width)
            {
                return;
            }

            ImageAttributes imageAttributes = new ImageAttributes();
            ColorMap colorMap = new ColorMap();

            colorMap.OldColor = Color.FromArgb(255, 0, 255, 0);
            colorMap.NewColor = Color.FromArgb(0, 0, 0, 0);
            ColorMap[] remapTable = { colorMap };

            imageAttributes.SetRemapTable(remapTable, ColorAdjustType.Bitmap);

            float transparency = 0.5F;
            if (watermarkTransparency >= 1 && watermarkTransparency <= 10)
            {
                transparency = (watermarkTransparency / 10.0F);
            }
            
            float[][] colorMatrixElements = {
                                                new float[] {1.0f,  0.0f,  0.0f,  0.0f, 0.0f},
                                                new float[] {0.0f,  1.0f,  0.0f,  0.0f, 0.0f},
                                                new float[] {0.0f,  0.0f,  1.0f,  0.0f, 0.0f},
                                                new float[] {0.0f,  0.0f,  0.0f,  transparency, 0.0f},
                                                new float[] {0.0f,  0.0f,  0.0f,  0.0f, 1.0f}
                                            };

            ColorMatrix colorMatrix = new ColorMatrix(colorMatrixElements);

            imageAttributes.SetColorMatrix(colorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);

            int xpos = 0;
            int ypos = 0;

            switch (watermarkStatus)
            {
                case 1:
                    xpos = (int)(img.Width * (float).01);
                    ypos = (int)(img.Height * (float).01);
                    break;
                case 2:
                    xpos = (int)((img.Width * (float).50) - (watermark.Width / 2));
                    ypos = (int)(img.Height * (float).01);
                    break;
                case 3:
                    xpos = (int)((img.Width * (float).99) - (watermark.Width));
                    ypos = (int)(img.Height * (float).01);
                    break;
                case 4:
                    xpos = (int)(img.Width * (float).01);
                    ypos = (int)((img.Height * (float).50) - (watermark.Height / 2));
                    break;
                case 5:
                    xpos = (int)((img.Width * (float).50) - (watermark.Width / 2));
                    ypos = (int)((img.Height * (float).50) - (watermark.Height / 2));
                    break;
                case 6:
                    xpos = (int)((img.Width * (float).99) - (watermark.Width));
                    ypos = (int)((img.Height * (float).50) - (watermark.Height / 2));
                    break;
                case 7:
                    xpos = (int)(img.Width * (float).01);
                    ypos = (int)((img.Height * (float).99) - watermark.Height);
                    break;
                case 8:
                    xpos = (int)((img.Width * (float).50) - (watermark.Width / 2));
                    ypos = (int)((img.Height * (float).99) - watermark.Height);
                    break;
                case 9:
                    xpos = (int)((img.Width * (float).99) - (watermark.Width));
                    ypos = (int)((img.Height * (float).99) - watermark.Height);
                    break;
                case 10:
                    var x = Convert.ToInt32(Math.Floor((img.Width - watermark.Width) * 0.9));
                    var y = Convert.ToInt32(Math.Floor((img.Height - watermark.Height) * 0.9));
                    Random rdm = new Random();
                    xpos = rdm.Next(x);
                    ypos = rdm.Next(y);
                    break;
            }

            g.DrawImage(watermark, new Rectangle(xpos, ypos, watermark.Width, watermark.Height), 0, 0, watermark.Width, watermark.Height, GraphicsUnit.Pixel, imageAttributes);

            ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
            ImageCodecInfo ici = null;
            foreach (ImageCodecInfo codec in codecs)
            {
                if (codec.MimeType.IndexOf("jpeg") > -1)
                {
                    ici = codec;
                }
            }
            EncoderParameters encoderParams = new EncoderParameters();
            long[] qualityParam = new long[1];
            if (quality < 0 || quality > 100)
            {
                quality = 80;
            }

            qualityParam[0] = quality;

            EncoderParameter encoderParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, qualityParam);
            encoderParams.Param[0] = encoderParam;

            if (ici != null)
            {
                img.Save(filename, ici, encoderParams);
            }
            else
            {
                img.Save(filename);
            }
            g.Dispose();
            img.Dispose();
            watermark.Dispose();
            imageAttributes.Dispose();
        }

        /// <summary>
        /// 文字水印
        /// </summary>
        /// <param name="imgPath">图片路径</param>
        /// <param name="filename">保存文件名及路径</param>
        /// <param name="watermarkText">水印文字</param>
        /// <param name="watermarkStatus">图片水印位置 </param>
        /// <param name="quality">附加水印图片质量,0-100</param>
        /// <param name="fontsize">字体大小</param>
        /// <param name="opacity">水印透明度</param>
        /// <param name="fontname">字体</param>
        public static void AddImageSignText(string imgPath, string filename, string watermarkText, int watermarkStatus, int quality, int fontsize,int opacity=100, string fontname = "微软雅黑")
        {
            var md5 = MD5Helper.MD5Encrypt32ToLower(imgPath);
            byte[] _ImageBytes = File.ReadAllBytes(imgPath);
            Image img = Image.FromStream(new MemoryStream(_ImageBytes));
            Graphics g = Graphics.FromImage(img);
            try
            {
                Font drawFont = new Font(fontname, fontsize, FontStyle.Regular, GraphicsUnit.Pixel);
                SizeF crSize;
                crSize = g.MeasureString(watermarkText, drawFont);

                float xpos = 0;
                float ypos = 0;

                switch (watermarkStatus)
                {
                    case 1:
                        xpos = (float)img.Width * (float).01;
                        ypos = (float)img.Height * (float).01;
                        break;
                    case 2:
                        xpos = ((float)img.Width * (float).50) - (crSize.Width / 2);
                        ypos = (float)img.Height * (float).01;
                        break;
                    case 3:
                        xpos = ((float)img.Width * (float).99) - crSize.Width;
                        ypos = (float)img.Height * (float).01;
                        break;
                    case 4:
                        xpos = (float)img.Width * (float).01;
                        ypos = ((float)img.Height * (float).50) - (crSize.Height / 2);
                        break;
                    case 5:
                        xpos = ((float)img.Width * (float).50) - (crSize.Width / 2);
                        ypos = ((float)img.Height * (float).50) - (crSize.Height / 2);
                        break;
                    case 6:
                        xpos = ((float)img.Width * (float).99) - crSize.Width;
                        ypos = ((float)img.Height * (float).50) - (crSize.Height / 2);
                        break;
                    case 7:
                        xpos = (float)img.Width * (float).01;
                        ypos = ((float)img.Height * (float).99) - crSize.Height;
                        break;
                    case 8:
                        xpos = ((float)img.Width * (float).50) - (crSize.Width / 2);
                        ypos = ((float)img.Height * (float).99) - crSize.Height;
                        break;
                    case 9:
                        xpos = ((float)img.Width * (float).99) - crSize.Width;
                        ypos = ((float)img.Height * (float).99) - crSize.Height;
                        break;
                    case 10:
                        bool flag = true;

                        while (flag)
                        {
                            Random rdm = new Random();
                            var x = rdm.Next(Convert.ToInt32(Math.Floor(img.Width - crSize.Width)));
                            var y = rdm.Next(Convert.ToInt32(Math.Floor(img.Height - crSize.Height)));
                            xpos = (float)x;
                            ypos = (float)y;
                            if (dic != null && dic.Count > 0)
                            {
                                if (dic.ContainsKey(md5))
                                {
                                    var dicTemp = dic[md5];
                                    int num = 0;
                                    foreach (var item in dicTemp)
                                    {
                                        if (Math.Abs(item.Key - xpos) <= crSize.Width && Math.Abs(item.Value - ypos) <= crSize.Height)
                                        {
                                            num++;
                                        }
                                    }
                                    if (num <= 0)
                                    {
                                        dicXY = dic[md5];
                                        dicXY.Add(xpos, ypos);
                                        dic[md5] = dicXY;
                                        flag = false;
                                    }
                                }
                                else
                                {
                                    dicXY = new Dictionary<float, float>();
                                    dicXY.Add(xpos, ypos);
                                    dic.Add(md5, dicXY);
                                    flag = false;
                                }
                            }
                            else
                            {
                                dic = new Dictionary<string, Dictionary<float, float>>();
                                dicXY = new Dictionary<float, float>();
                                dicXY.Add(xpos, ypos);
                                dic.Add(md5, dicXY);
                                flag = false;
                            }
                        }
                        break;
                }

                Brush whiteBrush = new SolidBrush(Color.FromArgb(opacity, 103, 109, 115)); //画文字用


                g.DrawString(watermarkText, drawFont, whiteBrush, xpos + 1, ypos + 1);
                g.DrawString(watermarkText, drawFont, whiteBrush, xpos, ypos);

                ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
                ImageCodecInfo ici = null;
                foreach (ImageCodecInfo codec in codecs)
                {
                    if (codec.MimeType.IndexOf("jpeg") > -1)
                    {
                        ici = codec;
                    }
                }
                EncoderParameters encoderParams = new EncoderParameters();
                long[] qualityParam = new long[1];
                if (quality < 0 || quality > 100)
                {
                    quality = 80;
                }

                qualityParam[0] = quality;

                EncoderParameter encoderParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, qualityParam);
                encoderParams.Param[0] = encoderParam;

                if (ici != null)
                {
                    img.Save(filename, ici, encoderParams);
                }
                else
                {
                    img.Save(filename);
                }
                g.Dispose();
                img.Dispose();
            }
            catch (Exception)
            {
                g.Dispose();
                img.Dispose();
            }
        }

    }
}
